package rep

import (
	"bufio"
	"fmt"
	"io"
	"os"
	"strings"
	"unicode"

	"gitcode.com/deyiyangyang/gascheme/ast"
	"gitcode.com/deyiyangyang/gascheme/eva"
	"gitcode.com/deyiyangyang/gascheme/lex"
	"gitcode.com/deyiyangyang/gascheme/obj"
	"gitcode.com/deyiyangyang/gascheme/par"
)

const PROMPT = ">>> "
const CONTINUATION_PROMPT = "... "

func StartPipe(in *bufio.Reader, out *bufio.Writer) {
	globalEnv := obj.NewGlobalEnvironment()
	eva.RegisterBuiltinProcedures(globalEnv)

	load(in, out, globalEnv)

	/*
		for {
			// 打印提示符（仅在交互模式下显示）
			var input strings.Builder
			for {
				// 读取用户输入的行
				line, err := in.ReadString('\n')
				if err != nil {
					// 如果是EOF且非交互模式，处理完所有输入后退出
					if err == io.EOF {
						// 处理最后一行（可能没有换行符）
						if len(strings.TrimSpace(line)) > 0 {
							input.WriteString(line)
							evalExpression(input.String(), out, globalEnv)
						}
						flushWriter(out)
						return
					}
					fmt.Fprintf(out, "Error reading input: %s\n", err)
					flushWriter(out)
					return
				}

				// 添加当前行到输入
				input.WriteString(line)

				// 检查是否需要更多输入（括号是否匹配）
				if needsMoreInput(input.String()) {
					// 如果是交互模式，显示续行提示符
					fmt.Fprintf(out, CONTINUATION_PROMPT)
					flushWriter(out)
					continue
				}

				// 括号匹配完成，跳出循环
				break
			}

			// 处理退出命令（仅在交互模式下）
			trimmed := strings.TrimSpace(input.String())
			if trimmed == "(exit)" || trimmed == "(quit)" {
				flushWriter(out)
				return
			}

			if len(trimmed) > 9 && trimmed[:5] == "(load" && unicode.IsSpace(rune(trimmed[5])) {
				l := lex.NewLexer(trimmed)
				p := par.NewParser(l)

				expr, err := p.ParseExpression()
				if err != nil {
					fmt.Println("parse error:", err)
					continue
				}

				list, ok := expr.(*ast.ListExpression)
				if !ok {
					continue
				}
				file, err := os.Open(list.Elements[1].TokenLiteral())
				if err != nil {
					fmt.Println("Error opening file:", err)
					return
				}
				defer file.Close()

				in := bufio.NewReader(file)
				out := bufio.NewWriter(os.Stdout)

				load(in, out, globalEnv)

				continue
			}
			//
			//}

			// 处理空输入
			if strings.TrimSpace(input.String()) == "" {
				continue
			}

			// 执行表达式
			evalExpression(input.String(), out, globalEnv)

		}
	*/
}
func StartTerminal(in *bufio.Reader, out *bufio.Writer) {
	globalEnv := obj.NewGlobalEnvironment()

	eva.RegisterBuiltinProcedures(globalEnv)

	printWelcomeMessage(out)
	flushWriter(out)
	for {
		// 打印提示符（仅在交互模式下显示）
		fmt.Fprintf(out, PROMPT)
		flushWriter(out)

		var input strings.Builder
		for {
			// 读取用户输入的行
			line, err := in.ReadString('\n')
			if err != nil {
				// 如果是EOF且非交互模式，处理完所有输入后退出
				if err == io.EOF {
					// 处理最后一行（可能没有换行符）
					if len(strings.TrimSpace(line)) > 0 {
						input.WriteString(line)
						evalExpression(input.String(), out, globalEnv)
					}
					flushWriter(out)
					return
				}
				fmt.Fprintf(out, "Error reading input: %s\n", err)
				flushWriter(out)
				return
			}

			// 添加当前行到输入
			input.WriteString(line)

			// 检查是否需要更多输入（括号是否匹配）
			if needsMoreInput(input.String()) {
				// 如果是交互模式，显示续行提示符
				fmt.Fprintf(out, CONTINUATION_PROMPT)
				flushWriter(out)
				continue
			}

			// 括号匹配完成，跳出循环
			break
		}

		// 处理退出命令（仅在交互模式下）
		trimmed := strings.TrimSpace(input.String())
		if trimmed == "(exit)" || trimmed == "(quit)" {
			flushWriter(out)
			return
		}

		if len(trimmed) > 9 && trimmed[:5] == "(load" && unicode.IsSpace(rune(trimmed[5])) {
			l := lex.NewLexer(trimmed)
			p := par.NewParser(l)

			expr, err := p.ParseExpression()
			if err != nil {
				fmt.Println("parse error:", err)
				continue
			}

			list, ok := expr.(*ast.ListExpression)
			if !ok {
				continue
			}
			file, err := os.Open(list.Elements[1].TokenLiteral())
			if err != nil {
				fmt.Println("Error opening file:", err)
				return
			}
			defer file.Close()

			in := bufio.NewReader(file)
			out := bufio.NewWriter(os.Stdout)

			load(in, out, globalEnv)
			continue
		}
		//
		//}

		// 处理空输入
		if strings.TrimSpace(input.String()) == "" {
			continue
		}

		// 执行表达式
		evalExpression(input.String(), out, globalEnv)

	}
}

// needsMoreInput checks if the input needs more lines to complete
// by checking if all parentheses are balanced
func needsMoreInput(input string) bool {
	// Create a lexer to tokenize the input
	l := lex.NewLexer(input)

	// Count parentheses
	leftParenCount := 0
	rightParenCount := 0

	for {
		token := l.NextToken()
		if token.Type == "EOF" {
			break
		}

		switch token.Type {
		case "LPAREN":
			leftParenCount++
		case "RPAREN":
			rightParenCount++
		}
	}

	// If we have more left parentheses than right ones, we need more input
	return leftParenCount > rightParenCount
}

// isInteractive checks if the input is coming from a terminal

// printWelcomeMessage打印欢迎信息
func printWelcomeMessage(out *bufio.Writer) {
	fmt.Fprintln(out, "Welcome to gaScheme!")
	fmt.Fprintln(out, "Type an expression to evaluate, or :q to quit.")
}

// flushWriter刷新写入器，确保输出显示
func flushWriter(out *bufio.Writer) {
	if err := out.Flush(); err != nil {
		fmt.Fprintf(os.Stderr, "Error flushing output: %s\n", err)
	}
}

// evalExpression执行表达式并输出结果
func evalExpression(input string, out *bufio.Writer, env obj.Environment) {
	// 创建词法分析器
	l := lex.NewLexer(input)

	// 创建解析器
	p := par.NewParser(l)

	// 解析表达式
	exprs, err := p.Parse()
	if err != nil {
		fmt.Fprintf(out, "Parse error: %s\n", err)
		flushWriter(out)
		return
	}

	for _, expr := range exprs {
		if expr == nil {
			return
		}
		result := eva.Eval(expr, env)

		// 打印结果
		printResult(result, out)
	}
}

// printResult打印表达式的评估结果
func printResult(result obj.Object, out *bufio.Writer) {
	if result == nil {
		fmt.Fprintln(out, "nil")
		flushWriter(out)
		return
	}

	// 处理错误对象
	if errObj, ok := result.(*obj.Error); ok {
		fmt.Fprintf(out, "Error: %s\n", errObj.Message)
		flushWriter(out)
		return
	}

	// Skip printing if the object implements NoPrint and returns true
	if noPrint, ok := result.(obj.NoPrint); ok && noPrint.NoPrint() {
		// Even though we don't print the result, we still need to ensure 
		// a newline so the prompt appears on the next line
		fmt.Fprintln(out, "")
		flushWriter(out)
		return
	}

	// 打印结果
	fmt.Fprintln(out, result.Inspect())
	flushWriter(out)
}

func load(in *bufio.Reader, out *bufio.Writer, globalEnv obj.Environment) {
	var input strings.Builder
	for {
		line, err := in.ReadString('\n')
		if err != nil {
			if err == io.EOF {
				if len(line) == 0 {
					break
				}
			} else {
				fmt.Println("Error reading input:", err)
				return
			}
		}

		// 添加当前行到输入
		input.WriteString(line)

		// 检查是否需要更多输入（括号是否匹配）
		if needsMoreInput(input.String()) {
			continue
		}

		// 处理退出命令（仅在交互模式下）
		trimmed := strings.TrimSpace(input.String())

		if len(trimmed) > 9 && trimmed[:5] == "(load" && unicode.IsSpace(rune(trimmed[5])) {
			l := lex.NewLexer(trimmed)
			p := par.NewParser(l)

			expr, err := p.ParseExpression()
			if err != nil {
				fmt.Println("parse error:", err)
				return
			}

			list, ok := expr.(*ast.ListExpression)
			if !ok {
				return
			}

			file, err := os.Open(list.Elements[1].TokenLiteral())
			if err != nil {
				fmt.Println("Error opening file:", err)
				return
			}
			defer file.Close()

			in := bufio.NewReader(file)
			out := bufio.NewWriter(os.Stdout)

			load(in, out, globalEnv)
		}

		if strings.TrimSpace(input.String()) == "" {
			continue
		}
		evalExpression(trimmed, out, globalEnv)
		input.Reset()

	}
}
